home *** CD-ROM | disk | FTP | other *** search
- /************************************
- *
-
- * file: SimpleOutMovies.c
- *
- * Program: SimpleOutMovies
- * This program creates a movie by spooling in PICTs from a folder
- * and adding adding them one at a time to the movie. When all PICTs have
- * been processed a sound track is added if one is present.
- *
- *
- * This program uses the sequence compression commands
- * which make smaller movie files by only saving
- * the changes between frames
- *
- * In this file we have the basic creation of a movie
- * and the addition of video track.
- *
- * By Guillermo A. Ortiz
- * April 1991
- *
- *
- * Heavily based on
- * Rich Williams' Movie Construction FD
- * January, 1991
- *
- * Apple Macintosh Developer Technical Support
- *
- * Copyright © 1989-1991 Apple Computer, Inc.
- * All rights reserved.
- *
- ************************************/
-
- /* Revisions:
-
- 08/06/91 --- Changed interface for NewMovie.
- Changed interface for NewMovieTrack.
- 08/13/91 --- Changed name GetCompressionSize in now GetMaxCompressionSize.
- 10/08/91 --- Changed all else.
- */
-
- /************************************
- * Inclusions
- ************************************/
-
- #define USEDUMP
-
- #if !defined(USEDUMP)
-
- #include <Types.h>
- #include <QuickDraw.h>
- #include <ToolUtils.h>
- #include <Events.h>
- #include <Controls.h>
- #include <Windows.h>
- #include <Dialogs.h>
- #include <Menus.h>
- #include <Desk.h>
- #include <SegLoad.h>
- #include <Files.h>
- #include <OSEvents.h>
- #include <Traps.h>
- #include <Fonts.h>
- #include <OSUtils.h>
- #include <Resources.h>
- #include <Memory.h>
- #include <Packages.h>
- #include <Lists.h>
- #include <Files.h>
- #include <Errors.h>
-
- #pragma dump "SimpleOutMovies.dump"
-
- #else
- #pragma load "SimpleOutMovies.dump"
- #endif
-
- /* QuickTime Includes */
- #include "QDOffscreen.h"
- #include "Movies.h"
- #include "MoviesFormat.h"
- #include "ImageCompression.h"
-
- // #define __GETCODECINFO__
- /************************************
- * Limits and Konstants
- ************************************/
- #define kFrameX 120 /* Width & Height */
- #define kFrameY 100
- #define kPixelSize 32
- #define kFrameCnt 1000 /* Number of frames to do */
- #define kTimeScale 10 /* 10 frames per second */
-
- /************************************
- * Types and globals
- ************************************/
- /* Drawer receives these fields */
- typedef struct
- {
- long frameX,frameY;
- long frameCnt;
- long pixelSize;
- } animationLimits;
-
- /************************************
- * Prototypes
- ************************************/
- static void InitToolbox(void);
- static void MakeFrames(animationLimits *, WindowPtr);
- static void ConstructMovie(void);
- static FixParameters(animationLimits *, WindowPtr, Rect *);
-
- void main(void);
-
- extern void GetDirectory(void);
- extern OSErr OpenOneFile(PicHandle, short);
- extern OSErr AddSoundTrack( Movie, Handle);
-
- extern Boolean CurDirValid;
-
- /************************************
- *
- * InitToolbox()
- * Start up the tool (and the movie tools!)
- *
- ************************************/
- void InitToolbox()
- {
- OSErr theErr;
-
- InitGraf((Ptr) &qd.thePort);
- InitFonts();
- FlushEvents(0xffff,0);
- InitWindows();
- InitMenus();
- InitDialogs(0);
- TEInit();
- InitCursor();
-
- theErr = EnterMovies(); /* Don't forget this. */
- if (theErr) DebugStr("\pEnterMovies Failed"); /* Real men don't use Alert Dialogs */
- }
-
-
- /************************************
- *
- * Construct Movie()
- * Make a window and call MakeFrames
- *
- ************************************/
- void ConstructMovie()
- {
- WindowPtr w;
- Rect r;
- animationLimits al;
-
- r.left = r.top = 0;
- r.right = kFrameX;
- r.bottom = kFrameY;
-
- OffsetRect(&r,100,100);
- w = NewCWindow(0,&r,"\pFrames",true,0,(WindowPtr)-1,true,0);
- SetPort(w);
-
- al.frameX = kFrameX;
- al.frameY = kFrameY;
- al.frameCnt = kFrameCnt;
- al.pixelSize = kPixelSize;
-
- MakeFrames(&al, w); /* write out lots of frames */
-
- CloseWindow(w);
- }
-
- /* Once we know where to look for the frames we want to
- change the parameters for the display window (this is cosmetic) and
- more important the limits for the animation based on the frame of the
- pictures. It is reasonable to assume that all frames will have the same dimentions.
- */
- FixParameters(al, w, r)
- animationLimits *al;
- WindowPtr w;
- Rect *r;
- {
- al->frameX = (r->right - r-> left) << 16; /* width and height are fixed values */
- al->frameY = (r->bottom - r->top) << 16;
- SizeWindow(w, (r->right - r-> left), (r->bottom - r->top), false);
- }
- /************************************
- *
- * MakeFrames(al)
- * Here is where all the work happens
- *
- ************************************/
- void MakeFrames(al, w)
-
- animationLimits *al;
- WindowPtr w;
-
- {
- short theErr; /* latest error return */
- short resRefNum; /* for file i/o */
- long i; /* the usual miscellaneous integer */
-
- /* Stuff for creating the file */
- Point dlgPos = {100,100}; /* Position the dialog box */
- SFReply sfr; /* StdFile reply */
- FSSpec mySpec; /* Data structure with filename, etc. */
- Handle mdrh;
- short resId;
-
- /* movie time vars */
- Movie gMovie;
- Track gTrack;
- Media gMedia;
-
- /* Stuff for drawing our frames */
- GWorldPtr myGWorld,oldGWorld;
- GDHandle oldGDevice;
- PixMap *pm,**pmH; /* our offscreen pixmap */
- Rect r;
- PicHandle pictureBuffer;
-
- /* Stuff for the compressor */
- char **compressedFrameBitsH; /* Buffer for the compressed data */
- long maxCompressedFrameSize; /* Max size of compressed frame was UNSIGNED*/
- long compressedFrameSize; /* Size of current compressed frame, was UNSIGNED*/
-
- CodecType codecType; /* Type of codec to use JPEG etc */
- CompressorComponent codecID; /* Which variation of codecType to use */
- short theDepth; /* Color depth to compress to */
- CodecQ theQuality; /* Quality to compress to */
- ImageDescription **imageDescriptorH; /* Contains info about the sample */
-
- CTabHandle ct = nil; /* assume no color table is needed */
-
- /* For frame differencing, we also have these */
- ImageSequence seqID; /* Which sequence is being compressed */
- unsigned char similarity; /* Measure of how similar the frame is to the previous one */
- long keyFrameRate; /* # samples per key frame */
- CodecQ mQuality; /* Motion quality */
- CodecInfo codecInf;
-
- /* Stuff for adding the sample */
- TimeValue sampTime; /* Time sample is added to media */
-
- /******************************
- *
- * Set values for Road Pizza compression
- * You would let the user pick it with a dialog
- *
- *******************************/
- codecID = anyCodec;
- codecType = (CodecType) 'rpza'; /* 'rpza'; */
- theDepth = 0; /* 16 is only color depth supported by 'rpza' */
- theQuality = 0x200; /* Quality is 0x100 to 0x300 */
-
- mQuality = 0x200;
- keyFrameRate = 10; /* 1 keyframe every 10 frames */
-
-
- /* this code shows how to make the call to get info on codec */
- /* one important use of this call is to determine the formats */
- /* supported by a codec. 'rpza' only supports 16 */
-
- theErr = GetCodecInfo(&codecInf, codecType, bestSpeedCodec);
- if (theErr )
- DebugStr("/pCouldn't GetCodecInfo");
-
- /******************************
- *
- * First we make an empty movie
- *
- *******************************/
-
- /* Prompt the user for a file name and create it */
- SFPutFile(dlgPos, "\pMovie file to create:","\pTempMovie",nil,&sfr);
- if (!sfr.good)
- return; /* Return if cancel pressed */
-
- /* Now we ask the user to point to the folder where the pictures are,
- then we allocate a handle to store the picts
- */
- GetDirectory();
-
- if (! CurDirValid) { /* flag if the user selected a folder */
- DebugStr("\pThe selection of folder failed");
- return;
- }
-
- /* In the sample we read in each PICT before calling drawpicture,
- in a real application it would be better to use spooling so that bigger
- PICTs can be used, the excuse is to make the sample simpler.
- See IM V for details on the spooling trick.
- */
- pictureBuffer = (PicHandle)NewHandle(10); /* Get a handle to store the picts */
- if ( MemError() ) {
- DebugStr("\pCould not allocate the buffer for picts");
- return; /* user needs to increase the app's partition */
- }
- /* Before we start the movie making we want to make sure the dimentions of the
- movie and window match the frames
- */
- for (i = 0; !(OpenOneFile(pictureBuffer, i+1)); i++) { /* it is possible the selected folder has a non-PICT file */
- if ( GetHandleSize((Handle)pictureBuffer) > 10 ) { /* in that case OpenOneFile set the handle size to ten */
- FixParameters(al, w, &((*pictureBuffer)->picFrame));
- break; /* ok we have our data lets go ahead */
- }
- }
-
- /* OK we have the files alligned and now we can start doing the movie stuff */
- ClearMoviesStickyError(); /* Clear any old errors */
-
- /* system 6.0.x fans will use this to create a FSSSpec out of the of SFGetFile reply */
- theErr = FSMakeFSSpec(sfr.vRefNum, 0, (unsigned char *) sfr.fName, &mySpec);
- if (theErr == fnfErr) theErr = 0;
- if (theErr) DebugStr("\pFSMakeFSSpec Failed");
-
- /******* The interface changed so instead of
- theErr = CreateMovieFile( &mySpec, 'TVOD',0,createMovieFileDeleteCurFile); we have: */
- theErr = CreateMovieFile( &mySpec, 'TVOD',0,createMovieFileDeleteCurFile, &resRefNum, nil);
- if (theErr) DebugStr("\pCreateMovieFile Failed");
-
- /******* The interface changed so instead of
- theErr = OpenMovieFile( &mySpec, &resRefNum, fsRdWrPerm, &mdrh ); */
- theErr = OpenMovieFile( &mySpec, &resRefNum, fsRdWrPerm);
- if (theErr) DebugStr("\pOpenMovieFile Failed");
-
- /* create media to use as a reference */
- theErr = NewAlias(nil, &mySpec, &(AliasHandle)mdrh);
- if (theErr) DebugStr("\NewAlias Failed");
-
- /* Create the movie, track and media */
- /******* The interface changed so instead of
- gMovie = NewMovie(0,60);
- we now have: */
- gMovie = NewMovie(0); /* the flags ask for a inactive movie */
- if (theErr = GetMoviesError()) DebugStr("\pNewMovie Failed");
-
- /******* The interface changed so instead of
- gTrack = NewMovieTrack(gMovie,(TimeValue) 0,kTimeScale,al->frameX,al->frameY);
- we now have: */
- gTrack = NewMovieTrack(gMovie,al->frameX,al->frameY, kNoVolume);
-
- if (theErr = GetMoviesError()) DebugStr("\pNewMovieTrack Failed");
-
- /******* changed interface ****/
- gMedia = NewTrackMedia(gTrack, VIDEO_TYPE,kTimeScale, mdrh, 'alis');
- if (theErr = GetMoviesError()) DebugStr("\pNewTrackMedia Failed");
-
- theErr = BeginMediaEdits( gMedia ); /* We do this since we are adding samples to the media */
- if (theErr) DebugStr("\pBeginMediaEdits Failed");
-
- /******************************
- *
- * Now make a new GWorld to draw the frames to be compressed
- *
- *******************************/
- GetGWorld(&oldGWorld,&oldGDevice); /* save the old port */
-
- r.left = r.top = 0;
- r.right = al->frameX >> 16; /* un_fix the values */
- r.bottom = al->frameY >> 16;
-
- if (theErr = NewGWorld(&myGWorld, al->pixelSize,&r,nil,nil,0))
- DebugStr("\pNewGWorld Failed");
- pmH = myGWorld->portPixMap; /* GetGWorldPixMap doesn't always work */
- LockPixels(pmH);
- HLock((Handle) pmH);
- pm = *pmH; /* pm is pointer to pixel-map */
-
- /******************************
- *
- * Now make the buffers and stuff for the compressor
- *
- *******************************/
-
- imageDescriptorH = (ImageDescription **)NewHandle( 4 ); /* handle for image descriptor */
- /***** The name changed from GetCompressionSize to */
- theErr = GetMaxCompressionSize(&pm,&r, theDepth,theQuality,
- codecType,codecID,&maxCompressedFrameSize); /* How big a buffer do we need? */
-
- if (theErr) DebugStr("\pGetCompressionSize Failed");
-
- compressedFrameBitsH = NewHandle(maxCompressedFrameSize); /* Make the buffer */
- if (!compressedFrameBitsH) DebugStr("\pUnable to allocate compression buffer");
-
- HLock(compressedFrameBitsH);
-
- /******************************
- *
- * Tell the codec manager we are about to start a sequence
- *
- *******************************/
-
- theErr = CompressSequenceBegin( &seqID,
- &pm, nil,
- &r, nil,
- theDepth, codecType, codecID,
- theQuality,
- mQuality, keyFrameRate,
- ct /* no clut */,
- codecFlagUpdatePrevious,
- imageDescriptorH);
-
- if (theErr) DebugStr("\pCompressSequenceBegin Failed");
-
- /******************************
- *
- * Now put the movie together one frame at a time
- *
- * We call the proc to load in the PICT, if it succeeds we
- * call DrawPicture into our GWorld and add the image to the movie.
- *
- *******************************/
-
- for (i = 0; !(OpenOneFile(pictureBuffer, i+1)); i++)
- { /* it is possible the selected folder has a non-PICT file */
- if ( GetHandleSize((Handle)pictureBuffer) > 10 ) { /* in that case OpenOneFile set the handle size to ten */
- if(Button()) /* A terrific user interface */
- {
- FlushEvents(0xffff,0);
- ExitToShell();
- }
-
- /******************************
- *
- * This is where we draw a single frame of the movie.
- * We're only drawing black and white here, into our big
- * 32-bit offscreen GWorld, because RAM is so cheap.
- *
- *******************************/
-
- SetGWorld(myGWorld,nil);
- EraseRect(&r); /* erase the whole area to white */
-
- DrawPicture( pictureBuffer, &r); /* replay the pict offscreen */
-
- /******************************
- *
- * Go back to the old GWorld (the Window)
- * and copybit the frame into it for something to watch
- *
- *******************************/
-
- SetGWorld(oldGWorld,oldGDevice);
- CopyBits((BitMap *) pm,(BitMap *)(*(PixMapHandle)(qd.thePort->portBits.baseAddr)),&r,&r,0,0);
-
- /******************************
- *
- * Compress the Frame
- *
- *******************************/
- compressedFrameSize = maxCompressedFrameSize;
-
- theErr = CompressSequenceFrame(seqID, /* the imageDescriptorH is filled here */
- &pm,
- &r,
- codecFlagUpdatePrevious,
- *compressedFrameBitsH,
- &compressedFrameSize,
- &similarity,
- nil);
-
-
- if (theErr) DebugStr("\pCompressSequenceFrame Failed");
-
- /******************************
- *
- * And add it to the media
- *
- *******************************/
-
- /***** sampleNotSync changed to mediaSampleNotSync *****/
- theErr = AddMediaSample(gMedia,compressedFrameBitsH,0L,compressedFrameSize,
- (TimeValue)1,(SampleDescriptionHandle) imageDescriptorH,1L,
- similarity?mediaSampleNotSync:0, &sampTime);
-
- if (theErr) DebugStr("\pAddMediaSample Failed");
- }
- /* And loop back for the next frame */
- }
-
- theErr = CDSequenceEnd(seqID); /* Tell the codec we're done with the sequence */
- if (theErr) DebugStr("\pCDSequenceEnd Failed");
-
- theErr = EndMediaEdits( gMedia ); /* We're done adding samples */
- if (theErr) DebugStr("\pEndMediaEdits Failed");
-
- /**** changed from
- theErr = InsertTrackMedia(gTrack,0L,GetMediaDuration(gMedia),0L,GetMediaDuration(gMedia)); */
- theErr = InsertMediaIntoTrack(gTrack,0L,0L,GetMediaDuration(gMedia), 0x00010000);
- if (theErr) DebugStr("\pInsertTrackMedia Failed");
-
- DisposHandle((Handle)pictureBuffer); /* dispose this handle to free its memory */
-
- /* At this point we have the video data accumulated, now we jump to the
- audio handling routine to see if the user wants to add sound to the movie.
- */
-
- AddSoundTrack( gMovie, mdrh); /* this thing return OSErr but I don't care */
-
- /******************************
- *
- * Now close up the movie
- * and throw out our buffers and stuff
- *
- *******************************/
- resId = 1;
- theErr = AddMovieResource( gMovie, resRefNum, &resId, (char *)sfr.fName );
- if (theErr) DebugStr("\pAddMovieResource Failed");
-
- theErr = CloseMovieFile( resRefNum );
- if (theErr) DebugStr("\CloseMovieFile Failed");
-
- DisposHandle( (Handle) mdrh);
- DisposHandle(compressedFrameBitsH);
- DisposHandle((Handle) imageDescriptorH);
- DisposeGWorld(myGWorld);
-
- }
-
-
- /******************************
- *
- * The main routine
- * It doesn't look like much but I'm proud of it
- *
- *******************************/
- void main()
- {
- InitToolbox(); /* Start up the tools */
- ConstructMovie(); /* Make the movie */
-
- }
-
-